﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using C1.Silverlight.PdfViewer;
using System.IO.IsolatedStorage;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using System.IO;
using PdfSharp.Drawing.Layout;
using FluxJpeg.Core;
using FluxJpeg.Core.Encoder;

namespace SilverlightPrinter
{
    public partial class PrintPreview : UserControl
    {
        private IsolatedStorageFile store;
        private string Filename = "teststore.pdf";

        private PdfDocument document;
        private PdfPage page;
        private XGraphics gfx;
        private XFont font;
        private double CurrentX;
        private double CurrentY;
        private Rect Margine;

        private string DefaultFontName = "msgothic";
        private double DefaultFontSize = 12;

        #region ** Initialize

        public PrintPreview()
        {
            InitializeComponent();
            InitPdfDocument();
            Loaded +=new RoutedEventHandler(PrintPreview_Loaded);
            Unloaded += new RoutedEventHandler(PrintPreview_Unloaded);
        }

        private void InitPdfDocument()
        {
            this.store = IsolatedStorageFile.GetUserStoreForApplication();
            if (store.FileExists(Filename))
                store.DeleteFile(Filename);

            this.document = new PdfDocument();
            this.document.Info.Title = "Silverlight Printer";
            this.document.Info.Author = "sasaco";
            this.document.Info.Subject = "Created with Silverlight Printer";
            this.document.Info.Keywords = "Silverlight, Printer"; 
            
            this.SetFont("", 0);
        }

        void PrintPreview_Loaded(object sender, RoutedEventArgs e)
        {
            using (IsolatedStorageFileStream stream = store.CreateFile(this.Filename))
            {
                this.document.Save(stream);
            }
            using (IsolatedStorageFileStream stream = store.OpenFile(this.Filename, FileMode.Open))
            {
                StreamReader reader = new StreamReader(stream);
                this.C1PdfViewer1.LoadDocument(stream);
            }
        }

        void PrintPreview_Unloaded(object sender, RoutedEventArgs e)
        {
            if (store.FileExists(Filename))
                store.DeleteFile(Filename);
            this.store.Dispose();
        }
        #endregion

        #region ** Settings

        public void SetMargine(double top, double Bottom, double Left, double Right)
        {
            Point topLeft = new Point(Left, top);
            Point BottomRight = new Point(page.Height.Point - Bottom, page.Height.Point - Bottom);
            this.Margine = new Rect(topLeft, BottomRight);
        }

        public void NewPage()
        {
            // Create an empty page
            this.page = document.AddPage();
            this.SetMargine(15, 15, 15, 15);
            this.CurrentX = this.Margine.Left;
            this.CurrentY = this.Margine.Top;
            // Get an XGraphics object for drawing
            this.gfx = XGraphics.FromPdfPage(this.page);
        }

        public void SetFont(string FontName, double FontSize)
        {
            XPdfFontOptions options = new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.Always);

            // Create a font
            if (FontName == "")
                FontName = this.DefaultFontName;

            if (FontSize <= 0)
                FontSize = this.DefaultFontSize;

            this.font = new XFont(FontName, FontSize, XFontStyle.Regular, options);
        }

        public Size PageSize()
        {
            Size result = new Size();
            result.Height = Margine.Height;
            result.Width = Margine.Width;
            return result;
        }
        #endregion

        #region ** Contents
        public void PrtTxt(double AfterLineSpacing, string strTxt)
        {
            // Draw the text
            this.gfx.DrawString(strTxt, this.font, XBrushes.Black, this.CurrentX, this.CurrentY);

            enter(AfterLineSpacing);
        }
        public void enter(double AfterLineSpacing)
        {
            int H = this.font.Height;
            this.CurrentY += H * AfterLineSpacing;
            this.CurrentX = this.Margine.Left;
        }
        public void PrtTable()
        {

        }

        public void PrtImg(WriteableBitmap wb)
        {
            byte[] b = Convert.FromBase64String(GetBase64Image(wb));
            using (MemoryStream ms = new MemoryStream(b))
            {
                XImage img = XImage.FromStream(ms);// XImage.FromStream(ms);
                this.gfx.DrawImage(img, this.CurrentX, this.CurrentY);

                this.CurrentY += img.PointHeight;
                this.CurrentX += img.PointWidth;
            }
        }
        private string GetBase64Image(WriteableBitmap bitmap)
        {
            int width = bitmap.PixelWidth;
            int height = bitmap.PixelHeight;
            int bands = 3;
            byte[][,] raster = new byte[bands][,];

            for (int i = 0; i < bands; i++)
            {
                raster[i] = new byte[width, height];
            }

            for (int row = 0; row < height; row++)
            {
                for (int column = 0; column < width; column++)
                {
                    int pixel = bitmap.Pixels[width * row + column];
                    raster[0][column, row] = (byte)(pixel >> 16);
                    raster[1][column, row] = (byte)(pixel >> 8);
                    raster[2][column, row] = (byte)pixel;
                }
            }

            ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
            FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);
            MemoryStream stream = new MemoryStream();
            JpegEncoder encoder = new JpegEncoder(img, 100, stream);
            encoder.Encode();

            stream.Seek(0, SeekOrigin.Begin);
            byte[] binaryData = new Byte[stream.Length];
            long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);

            string base64String =
                    System.Convert.ToBase64String(binaryData,
                                                  0,
                                                  binaryData.Length);

            return base64String;

        }

        #endregion

    }
}
